home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / BOXES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-18  |  20.4 KB  |  1,104 lines

  1. /****************************************************************************
  2. *                boxes.c
  3. *
  4. *  This module implements the box primitive.
  5. *  This file was written by Alexander Enzmann.  He wrote the code for
  6. *  boxes and generously provided us these enhancements.
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. #include "frame.h"
  27. #include "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "bbox.h"
  31. #include "boxes.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40.  
  41. /* Minimal intersection depth. */
  42.  
  43. #define DEPTH_TOLERANCE 1.0e-6
  44.  
  45. /* Two values are equal if their difference is small than CLOSE_TOLERANCE. */
  46.  
  47. #define CLOSE_TOLERANCE 1.0e-6
  48.  
  49. /* Side hit. */
  50.  
  51. #define SIDE_X_0 1
  52. #define SIDE_X_1 2
  53. #define SIDE_Y_0 3
  54. #define SIDE_Y_1 4
  55. #define SIDE_Z_0 5
  56. #define SIDE_Z_1 6
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Static functions
  62. ******************************************************************************/
  63. static int  All_Box_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  64. static int  Inside_Box PARAMS((VECTOR point, OBJECT *Object));
  65. static void Box_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
  66. static void Translate_Box PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  67. static void Rotate_Box PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  68. static void Scale_Box PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  69. static void Transform_Box PARAMS((OBJECT *Object, TRANSFORM *Trans));
  70. static void Invert_Box PARAMS((OBJECT *Object));
  71.  
  72.  
  73.  
  74. /*****************************************************************************
  75. * Local variables
  76. ******************************************************************************/
  77.  
  78. METHODS Box_Methods =
  79. {
  80.   All_Box_Intersections,
  81.   Inside_Box, Box_Normal,
  82.   Copy_Box, Translate_Box, Rotate_Box, Scale_Box, Transform_Box,
  83.   Invert_Box, Destroy_Box
  84. };
  85.  
  86.  
  87.  
  88. /*****************************************************************************
  89. *
  90. * FUNCTION
  91. *
  92. *   All_Box_Intersections
  93. *
  94. * INPUT
  95. *
  96. * OUTPUT
  97. *
  98. * RETURNS
  99. *
  100. * AUTHOR
  101. *
  102. *   Alexander Enzmann
  103. *
  104. * DESCRIPTION
  105. *
  106. *   -
  107. *
  108. * CHANGES
  109. *
  110. *   -
  111. *
  112. ******************************************************************************/
  113.  
  114. static int All_Box_Intersections(Object, Ray, Depth_Stack)
  115. OBJECT *Object;
  116. RAY *Ray;
  117. ISTACK *Depth_Stack;
  118. {
  119.   int Intersection_Found;
  120.   int Side1, Side2;
  121.   DBL Depth1, Depth2;
  122.   VECTOR IPoint;
  123.  
  124.   Increase_Counter(stats[Ray_Box_Tests]);
  125.  
  126.   Intersection_Found = FALSE;
  127.  
  128.   if (Intersect_Box(Ray, (BOX *)Object, &Depth1, &Depth2, &Side1, &Side2))
  129.   {
  130.     if (Depth1 > DEPTH_TOLERANCE)
  131.     {
  132.       VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
  133.  
  134.       if (Point_In_Clip(IPoint, Object->Clip))
  135.       {
  136.         push_entry_i1(Depth1,IPoint,Object,Side1,Depth_Stack);
  137.  
  138.         Intersection_Found = TRUE;
  139.       }
  140.     }
  141.  
  142.     VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
  143.  
  144.     if (Point_In_Clip(IPoint, Object->Clip))
  145.     {
  146.       push_entry_i1(Depth2,IPoint,Object,Side2,Depth_Stack);
  147.  
  148.       Intersection_Found = TRUE;
  149.     }
  150.   }
  151.  
  152.   if (Intersection_Found)
  153.   {
  154.     Increase_Counter(stats[Ray_Box_Tests_Succeeded]);
  155.   }
  156.  
  157.   return (Intersection_Found);
  158. }
  159.  
  160.  
  161.  
  162. /*****************************************************************************
  163. *
  164. * FUNCTION
  165. *
  166. *   Intersect_Box
  167. *
  168. * INPUT
  169. *
  170. * OUTPUT
  171. *
  172. * RETURNS
  173. *
  174. * AUTHOR
  175. *
  176. *   Alexander Enzmann
  177. *
  178. * DESCRIPTION
  179. *
  180. *   -
  181. *
  182. * CHANGES
  183. *
  184. *   Sep 1994 : Added code to decide which side was hit in the case
  185. *              intersection points are close to each other. This removes
  186. *              some ugly artefacts one could observe at the corners of
  187. *              boxes due to the usage of the wrong normal vector. [DB]
  188. *
  189. ******************************************************************************/
  190.  
  191. int Intersect_Box(Ray, box, Depth1, Depth2, Side1, Side2)
  192. RAY *Ray;
  193. BOX *box;
  194. DBL *Depth1, *Depth2;
  195. int *Side1, *Side2;
  196. {
  197.   int smin = 0, smax = 0;    /* Side hit for min/max intersection. */
  198.   DBL t, tmin, tmax;
  199.   VECTOR P, D;
  200.   DBL rdivx;
  201.   DBL rdivy;
  202.   DBL rdivz;
  203.  
  204.   /* Transform the point into the boxes space */
  205.  
  206.   if (box->Trans != NULL)
  207.   {
  208.     MInvTransPoint(P, Ray->Initial, box->Trans);
  209.     MInvTransDirection(D, Ray->Direction, box->Trans);
  210.   }
  211.   else
  212.   {
  213.     Assign_Vector(P, Ray->Initial);
  214.     Assign_Vector(D, Ray->Direction);
  215.   }
  216.  
  217.   tmin = 0.0;
  218.   tmax = BOUND_HUGE;
  219.  
  220.   /*
  221.    * Sides first.
  222.    */
  223.  
  224.   rdivx = (1.0 / D[X]);
  225.   rdivy = (1.0 / D[Y]);
  226.   rdivz = (1.0 / D[Z]);
  227.  
  228.   if (D[X] < -EPSILON)
  229.   {
  230. /*
  231.     t = (box->bounds[0][X] - P[X]) / D[X];
  232. */
  233.     t = (box->bounds[0][X] - P[X]) * rdivx;
  234.  
  235.     if (t < tmin) return(FALSE);
  236.  
  237.     if (t <= tmax)
  238.     {
  239.       smax = SIDE_X_0;
  240.       tmax = t;
  241.     }
  242.  
  243. /*
  244.     t = (box->bounds[1][X] - P[X]) / D[X];
  245. */
  246.     t = (box->bounds[1][X] - P[X]) * rdivx;
  247.  
  248.     if (t >= tmin)
  249.     {
  250.       if (t > tmax) return(FALSE);
  251.  
  252.       smin = SIDE_X_1;
  253.       tmin = t;
  254.     }
  255.   }
  256.   else
  257.   {
  258.     if (D[X] > EPSILON)
  259.     {
  260. /*
  261.     t = (box->bounds[1][X] - P[X]) / D[X];
  262. */
  263.     t = (box->bounds[1][X] - P[X]) * rdivx;
  264.  
  265.       if (t < tmin) return(FALSE);
  266.  
  267.       if (t <= tmax)
  268.       {
  269.         smax = SIDE_X_1;
  270.         tmax = t;
  271.       }
  272.  
  273. /*
  274.       t = (box->bounds[0][X] - P[X]) / D[X];
  275. */
  276.       t = (box->bounds[0][X] - P[X]) * rdivx;
  277.  
  278.       if (t >= tmin)
  279.       {
  280.         if (t > tmax) return(FALSE);
  281.  
  282.         smin = SIDE_X_0;
  283.         tmin = t;
  284.       }
  285.     }
  286.     else
  287.     {
  288.       if ((P[X] < box->bounds[0][X]) || (P[X] > box->bounds[1][X]))
  289.       {
  290.         return(FALSE);
  291.       }
  292.     }
  293.   }
  294.  
  295.   /*
  296.    * Check Top/Bottom.
  297.    */
  298.  
  299.   if (D[Y] < -EPSILON)
  300.   {
  301. /*
  302.     t = (box->bounds[0][Y] - P[Y]) / D[Y];
  303. */
  304.     t = (box->bounds[0][Y] - P[Y]) * rdivy;
  305.  
  306.     if (t < tmin) return(FALSE);
  307.  
  308.     if (t <= tmax - CLOSE_TOLERANCE)
  309.     {
  310.       smax = SIDE_Y_0;
  311.       tmax = t;
  312.     }
  313.     else
  314.     {
  315.       /*
  316.        * If intersection points are close to each other find out
  317.        * which side to use, i.e. is most probably hit. [DB 9/94]
  318.        */
  319.  
  320.       if (t <= tmax + CLOSE_TOLERANCE)
  321.       {
  322.         if (-D[Y] > fabs(D[X])) smax = SIDE_Y_0;
  323.       }
  324.     }
  325.  
  326. /*
  327.     t = (box->bounds[1][Y] - P[Y]) / D[Y];
  328. */
  329.     t = (box->bounds[1][Y] - P[Y]) * rdivy;
  330.  
  331.     if (t >= tmin + CLOSE_TOLERANCE)
  332.     {
  333.       if (t > tmax) return(FALSE);
  334.  
  335.       smin = SIDE_Y_1;
  336.       tmin = t;
  337.     }
  338.     else
  339.     {
  340.       /*
  341.        * If intersection points are close to each other find out
  342.        * which side to use, i.e. is most probably hit. [DB 9/94]
  343.        */
  344.  
  345.       if (t >= tmin - CLOSE_TOLERANCE)
  346.       {
  347.         if (-D[Y] > fabs(D[X])) smin = SIDE_Y_1;
  348.       }
  349.     }
  350.   }
  351.   else
  352.   {
  353.     if (D[Y] > EPSILON)
  354.     {
  355.  
  356. /*
  357.       t = (box->bounds[1][Y] - P[Y]) / D[Y];
  358. */
  359.       t = (box->bounds[1][Y] - P[Y]) * rdivy;
  360.  
  361.       if (t < tmin) return(FALSE);
  362.  
  363.       if (t <= tmax - CLOSE_TOLERANCE)
  364.       {
  365.         smax = SIDE_Y_1;
  366.         tmax = t;
  367.       }
  368.       else
  369.       {
  370.         /*
  371.          * If intersection points are close to each other find out
  372.          * which side to use, i.e. is most probably hit. [DB 9/94]
  373.          */
  374.  
  375.         if (t <= tmax + CLOSE_TOLERANCE)
  376.         {
  377.           if (D[Y] > fabs(D[X])) smax = SIDE_Y_1;
  378.         }
  379.       }
  380.  
  381. /*
  382.       t = (box->bounds[0][Y] - P[Y]) / D[Y];
  383. */
  384.       t = (box->bounds[0][Y] - P[Y]) * rdivy;
  385.  
  386.       if (t >= tmin + CLOSE_TOLERANCE)
  387.       {
  388.         if (t > tmax) return(FALSE);
  389.  
  390.         smin = SIDE_Y_0;
  391.         tmin = t;
  392.       }
  393.       else
  394.       {
  395.         /*
  396.          * If intersection points are close to each other find out
  397.          * which side to use, i.e. is most probably hit. [DB 9/94]
  398.          */
  399.  
  400.         if (t >= tmin - CLOSE_TOLERANCE)
  401.         {
  402.           if (D[Y] > fabs(D[X])) smin = SIDE_Y_0;
  403.         }
  404.       }
  405.     }
  406.     else
  407.     {
  408.       if ((P[Y] < box->bounds[0][Y]) || (P[Y] > box->bounds[1][Y]))
  409.       {
  410.         return(FALSE);
  411.       }
  412.     }
  413.   }
  414.  
  415.   /* Now front/back */
  416.  
  417.   if (D[Z] < -EPSILON)
  418.   {
  419.  
  420. /*
  421.     t = (box->bounds[0][Z] - P[Z]) / D[Z];
  422. */
  423.     t = (box->bounds[0][Z] - P[Z]) * rdivz;
  424.  
  425.     if (t < tmin) return(FALSE);
  426.  
  427.     if (t <= tmax - CLOSE_TOLERANCE)
  428.     {
  429.       smax = SIDE_Z_0;
  430.       tmax = t;
  431.     }
  432.     else
  433.     {
  434.       /*
  435.        * If intersection points are close to each other find out
  436.        * which side to use, i.e. is most probably hit. [DB 9/94]
  437.        */
  438.  
  439.       if (t <= tmax + CLOSE_TOLERANCE)
  440.       {
  441.         switch (smax)
  442.         {
  443.           case SIDE_X_0 :
  444.           case SIDE_X_1 : if (-D[Z] > fabs(D[X])) smax = SIDE_Z_0; break;
  445.  
  446.           case SIDE_Y_0 :
  447.           case SIDE_Y_1 : if (-D[Z] > fabs(D[Y])) smax = SIDE_Z_0; break;
  448.         }
  449.       }
  450.     }
  451.  
  452. /*
  453.     t = (box->bounds[1][Z] - P[Z]) / D[Z];
  454. */
  455.     t = (box->bounds[1][Z] - P[Z]) * rdivz;
  456.  
  457.     if (t >= tmin + CLOSE_TOLERANCE)
  458.     {
  459.       if (t > tmax) return(FALSE);
  460.  
  461.       smin = SIDE_Z_1;
  462.       tmin = t;
  463.     }
  464.     else
  465.     {
  466.       /*
  467.        * If intersection points are close to each other find out
  468.        * which side to use, i.e. is most probably hit. [DB 9/94]
  469.        */
  470.  
  471.       if (t >= tmin - CLOSE_TOLERANCE)
  472.       {
  473.         switch (smin)
  474.         {
  475.           case SIDE_X_0 :
  476.           case SIDE_X_1 : if (-D[Z] > fabs(D[X])) smin = SIDE_Z_1; break;
  477.  
  478.           case SIDE_Y_0 :
  479.           case SIDE_Y_1 : if (-D[Z] > fabs(D[Y])) smin = SIDE_Z_1; break;
  480.         }
  481.       }
  482.     }
  483.   }
  484.   else
  485.   {
  486.     if (D[Z] > EPSILON)
  487.     {
  488.  
  489. /*
  490.       t = (box->bounds[1][Z] - P[Z]) / D[Z];
  491. */
  492.       t = (box->bounds[1][Z] - P[Z]) * rdivz;
  493.  
  494.       if (t < tmin) return(FALSE);
  495.  
  496.       if (t <= tmax - CLOSE_TOLERANCE)
  497.       {
  498.         smax = SIDE_Z_1;
  499.         tmax = t;
  500.       }
  501.       else
  502.       {
  503.         /*
  504.          * If intersection points are close to each other find out
  505.          * which side to use, i.e. is most probably hit. [DB 9/94]
  506.          */
  507.  
  508.         if (t <= tmax + CLOSE_TOLERANCE)
  509.         {
  510.           switch (smax)
  511.           {
  512.             case SIDE_X_0 :
  513.             case SIDE_X_1 : if (D[Z] > fabs(D[X])) smax = SIDE_Z_1; break;
  514.  
  515.             case SIDE_Y_0 :
  516.             case SIDE_Y_1 : if (D[Z] > fabs(D[Y])) smax = SIDE_Z_1; break;
  517.           }
  518.         }
  519.       }
  520.  
  521. /*
  522.       t = (box->bounds[0][Z] - P[Z]) / D[Z];
  523. */
  524.       t = (box->bounds[0][Z] - P[Z]) * rdivz;
  525.  
  526.       if (t >= tmin + CLOSE_TOLERANCE)
  527.       {
  528.         if (t > tmax) return(FALSE);
  529.  
  530.         smin = SIDE_Z_0;
  531.         tmin = t;
  532.       }
  533.       else
  534.       {
  535.         /*
  536.          * If intersection points are close to each other find out
  537.          * which side to use, i.e. is most probably hit. [DB 9/94]
  538.          */
  539.  
  540.         if (t >= tmin - CLOSE_TOLERANCE)
  541.         {
  542.           switch (smin)
  543.           {
  544.             case SIDE_X_0 :
  545.             case SIDE_X_1 : if (D[Z] > fabs(D[X])) smin = SIDE_Z_0; break;
  546.  
  547.             case SIDE_Y_0 :
  548.             case SIDE_Y_1 : if (D[Z] > fabs(D[Y])) smin = SIDE_Z_0; break;
  549.           }
  550.         }
  551.       }
  552.     }
  553.     else
  554.     {
  555.       if ((P[Z] < box->bounds[0][Z]) || (P[Z] > box->bounds[1][Z]))
  556.       {
  557.         return(FALSE);
  558.       }
  559.     }
  560.   }
  561.  
  562.   if (tmax < DEPTH_TOLERANCE)
  563.   {
  564.     return (FALSE);
  565.   }
  566.  
  567.   *Depth1 = tmin;
  568.   *Depth2 = tmax;
  569.  
  570.   *Side1 = smin;
  571.   *Side2 = smax;
  572.  
  573.   return(TRUE);
  574. }
  575.  
  576.  
  577.  
  578. /*****************************************************************************
  579. *
  580. * FUNCTION
  581. *
  582. *   Inside_Box
  583. *
  584. * INPUT
  585. *
  586. * OUTPUT
  587. *
  588. * RETURNS
  589. *
  590. * AUTHOR
  591. *
  592. *   Alexander Enzmann
  593. *
  594. * DESCRIPTION
  595. *
  596. *   -
  597. *
  598. * CHANGES
  599. *
  600. *   -
  601. *
  602. ******************************************************************************/
  603.  
  604. static int Inside_Box(IPoint, Object)
  605. VECTOR IPoint;
  606. OBJECT *Object;
  607. {
  608.   VECTOR New_Point;
  609.   BOX *box = (BOX *) Object;
  610.  
  611.   /* Transform the point into box space. */
  612.  
  613.   if (box->Trans != NULL)
  614.   {
  615.     MInvTransPoint(New_Point, IPoint, box->Trans);
  616.   }
  617.   else
  618.   {
  619.     Assign_Vector(New_Point,IPoint);
  620.   }
  621.  
  622.   /* Test to see if we are outside the box. */
  623.  
  624.   if ((New_Point[X] < box->bounds[0][X]) || (New_Point[X] > box->bounds[1][X]))
  625.   {
  626.     return (Test_Flag(box, INVERTED_FLAG));
  627.   }
  628.  
  629.   if ((New_Point[Y] < box->bounds[0][Y]) || (New_Point[Y] > box->bounds[1][Y]))
  630.   {
  631.     return (Test_Flag(box, INVERTED_FLAG));
  632.   }
  633.  
  634.   if ((New_Point[Z] < box->bounds[0][Z]) || (New_Point[Z] > box->bounds[1][Z]))
  635.   {
  636.     return (Test_Flag(box, INVERTED_FLAG));
  637.   }
  638.  
  639.   /* Inside the box. */
  640.  
  641.   return (!Test_Flag(box, INVERTED_FLAG));
  642. }
  643.  
  644.  
  645.  
  646. /*****************************************************************************
  647. *
  648. * FUNCTION
  649. *
  650. *   Box_Normal
  651. *
  652. * INPUT
  653. *
  654. * OUTPUT
  655. *
  656. * RETURNS
  657. *
  658. * AUTHOR
  659. *
  660. *   Alexander Enzmann
  661. *
  662. * DESCRIPTION
  663. *
  664. *   -
  665. *
  666. * CHANGES
  667. *
  668. *   -
  669. *
  670. ******************************************************************************/
  671.  
  672. static void Box_Normal(Result, Object, Inter)
  673. OBJECT *Object;
  674. VECTOR Result;
  675. INTERSECTION *Inter;
  676. {
  677.   switch (Inter->i1)
  678.   {
  679.     case SIDE_X_0: Make_Vector(Result, -1.0,  0.0,  0.0); break;
  680.     case SIDE_X_1: Make_Vector(Result,  1.0,  0.0,  0.0); break;
  681.     case SIDE_Y_0: Make_Vector(Result,  0.0, -1.0,  0.0); break;
  682.     case SIDE_Y_1: Make_Vector(Result,  0.0,  1.0,  0.0); break;
  683.     case SIDE_Z_0: Make_Vector(Result,  0.0,  0.0, -1.0); break;
  684.     case SIDE_Z_1: Make_Vector(Result,  0.0,  0.0,  1.0); break;
  685.  
  686.     default: Error("Unknown box side in Box_Normal().\n");
  687.   }
  688.  
  689.   /* Transform the point into the boxes space. */
  690.  
  691.   if (((BOX *)Object)->Trans != NULL)
  692.   {
  693.     MTransNormal(Result, Result, ((BOX *)Object)->Trans);
  694.  
  695.     VNormalize(Result, Result);
  696.   }
  697. }
  698.  
  699.  
  700.  
  701. /*****************************************************************************
  702. *
  703. * FUNCTION
  704. *
  705. *   Translate_Box
  706. *
  707. * INPUT
  708. *
  709. * OUTPUT
  710. *
  711. * RETURNS
  712. *
  713. * AUTHOR
  714. *
  715. *   Alexander Enzmann
  716. *
  717. * DESCRIPTION
  718. *
  719. *   -
  720. *
  721. * CHANGES
  722. *
  723. *   -
  724. *
  725. ******************************************************************************/
  726.  
  727. static void Translate_Box(Object, Vector, Trans)
  728. OBJECT *Object;
  729. VECTOR Vector;
  730. TRANSFORM *Trans;
  731. {
  732.   if (((BOX *)Object)->Trans == NULL)
  733.   {
  734.     VAddEq(((BOX *)Object)->bounds[0], Vector);
  735.  
  736.     VAddEq(((BOX *)Object)->bounds[1], Vector);
  737.  
  738.     Compute_Box_BBox((BOX *)Object);
  739.   }
  740.   else
  741.   {
  742.     Transform_Box(Object, Trans);
  743.   }
  744. }
  745.  
  746.  
  747.  
  748. /*****************************************************************************
  749. *
  750. * FUNCTION
  751. *
  752. *   Rotate_Box
  753. *
  754. * INPUT
  755. *
  756. * OUTPUT
  757. *
  758. * RETURNS
  759. *
  760. * AUTHOR
  761. *
  762. *   Alexander Enzmann
  763. *
  764. * DESCRIPTION
  765. *
  766. *   -
  767. *
  768. * CHANGES
  769. *
  770. *   -
  771. *
  772. ******************************************************************************/
  773.  
  774. static void Rotate_Box(Object, Vector, Trans)
  775. OBJECT *Object;
  776. VECTOR Vector;
  777. TRANSFORM *Trans;
  778. {
  779.   Transform_Box(Object, Trans);
  780. }
  781.  
  782.  
  783.  
  784. /*****************************************************************************
  785. *
  786. * FUNCTION
  787. *
  788. *   Scale_Box
  789. *
  790. * INPUT
  791. *
  792. * OUTPUT
  793. *
  794. * RETURNS
  795. *
  796. * AUTHOR
  797. *
  798. *   Alexander Enzmann
  799. *
  800. * DESCRIPTION
  801. *
  802. *   -
  803. *
  804. * CHANGES
  805. *
  806. *   -
  807. *
  808. ******************************************************************************/
  809.  
  810. static void Scale_Box(Object, Vector, Trans)
  811. OBJECT *Object;
  812. VECTOR Vector;
  813. TRANSFORM *Trans;
  814. {
  815.   DBL temp;
  816.   BOX *Box = (BOX *)Object;
  817.  
  818.   if (((BOX *)Object)->Trans == NULL)
  819.   {
  820.     VEvaluateEq(Box->bounds[0], Vector);
  821.     VEvaluateEq(Box->bounds[1], Vector);
  822.  
  823.     if (Box->bounds[0][X] > Box->bounds[1][X])
  824.     {
  825.       temp = Box->bounds[0][X];
  826.  
  827.       Box->bounds[0][X] = Box->bounds[1][X];
  828.       Box->bounds[1][X] = temp;
  829.     }
  830.  
  831.     if (Box->bounds[0][Y] > Box->bounds[1][Y])
  832.     {
  833.       temp = Box->bounds[0][Y];
  834.  
  835.       Box->bounds[0][Y] = Box->bounds[1][Y];
  836.       Box->bounds[1][Y] = temp;
  837.     }
  838.  
  839.     if (Box->bounds[0][Z] > Box->bounds[1][Z])
  840.     {
  841.       temp = Box->bounds[0][Z];
  842.  
  843.       Box->bounds[0][Z] = Box->bounds[1][Z];
  844.       Box->bounds[1][Z] = temp;
  845.     }
  846.  
  847.     Compute_Box_BBox((BOX *)Object);
  848.   }
  849.   else
  850.   {
  851.     Transform_Box(Object, Trans);
  852.   }
  853. }
  854.  
  855.  
  856.  
  857. /*****************************************************************************
  858. *
  859. * FUNCTION
  860. *
  861. *   Invert_Box
  862. *
  863. * INPUT
  864. *
  865. * OUTPUT
  866. *
  867. * RETURNS
  868. *
  869. * AUTHOR
  870. *
  871. *   Alexander Enzmann
  872. *
  873. * DESCRIPTION
  874. *
  875. *   -
  876. *
  877. * CHANGES
  878. *
  879. *   -
  880. *
  881. ******************************************************************************/
  882.  
  883. static void Invert_Box(Object)
  884. OBJECT *Object;
  885. {
  886.   Invert_Flag(Object, INVERTED_FLAG);
  887. }
  888.  
  889.  
  890.  
  891. /*****************************************************************************
  892. *
  893. * FUNCTION
  894. *
  895. *   Transform_Box
  896. *
  897. * INPUT
  898. *
  899. * OUTPUT
  900. *
  901. * RETURNS
  902. *
  903. * AUTHOR
  904. *
  905. *   Alexander Enzmann
  906. *
  907. * DESCRIPTION
  908. *
  909. *   -
  910. *
  911. * CHANGES
  912. *
  913. *   -
  914. *
  915. ******************************************************************************/
  916.  
  917. static void Transform_Box(Object, Trans)
  918. OBJECT *Object;
  919. TRANSFORM *Trans;
  920. {
  921.   BOX *box = (BOX *)Object;
  922.  
  923.   if (box->Trans == NULL)
  924.   {
  925.     box->Trans = Create_Transform();
  926.   }
  927.  
  928.   Compose_Transforms(box->Trans, Trans);
  929.  
  930.   Compute_Box_BBox(box);
  931. }
  932.  
  933.  
  934.  
  935. /*****************************************************************************
  936. *
  937. * FUNCTION
  938. *
  939. *   Create_Box
  940. *
  941. * INPUT
  942. *
  943. * OUTPUT
  944. *
  945. * RETURNS
  946. *
  947. * AUTHOR
  948. *
  949. *   Alexander Enzmann
  950. *
  951. * DESCRIPTION
  952. *
  953. *   -
  954. *
  955. * CHANGES
  956. *
  957. *   -
  958. *
  959. ******************************************************************************/
  960.  
  961. BOX *Create_Box()
  962. {
  963.   BOX *New;
  964.  
  965.   New = (BOX *)POV_MALLOC(sizeof(BOX), "box");
  966.  
  967.   INIT_OBJECT_FIELDS(New, BOX_OBJECT, &Box_Methods)
  968.  
  969.   Make_Vector(New->bounds[0], -1.0, -1.0, -1.0);
  970.   Make_Vector(New->bounds[1],  1.0,  1.0,  1.0);
  971.  
  972.   Make_BBox(New->BBox, -1.0, -1.0, -1.0, 2.0, 2.0, 2.0);
  973.  
  974.   New->Trans = NULL;
  975.  
  976.   return (New);
  977. }
  978.  
  979.  
  980.  
  981. /*****************************************************************************
  982. *
  983. * FUNCTION
  984. *
  985. *   Copy_Box
  986. *
  987. * INPUT
  988. *
  989. * OUTPUT
  990. *
  991. * RETURNS
  992. *
  993. * AUTHOR
  994. *
  995. *   Alexander Enzmann
  996. *
  997. * DESCRIPTION
  998. *
  999. *   -
  1000. *
  1001. * CHANGES
  1002. *
  1003. *   -
  1004. *
  1005. ******************************************************************************/
  1006.  
  1007. void *Copy_Box(Object)
  1008. OBJECT *Object;
  1009. {
  1010.   BOX *New;
  1011.  
  1012.   New  = Create_Box();
  1013.  
  1014.   /* Copy box. */
  1015.  
  1016.   *New = *((BOX *)Object);
  1017.  
  1018.   New->Trans = Copy_Transform(((BOX *)Object)->Trans);
  1019.  
  1020.   return (New);
  1021. }
  1022.  
  1023.  
  1024.  
  1025. /*****************************************************************************
  1026. *
  1027. * FUNCTION
  1028. *
  1029. *   Destroy_Box
  1030. *
  1031. * INPUT
  1032. *
  1033. * OUTPUT
  1034. *
  1035. * RETURNS
  1036. *
  1037. * AUTHOR
  1038. *
  1039. *   Alexander Enzmann
  1040. *
  1041. * DESCRIPTION
  1042. *
  1043. *   -
  1044. *
  1045. * CHANGES
  1046. *
  1047. *   -
  1048. *
  1049. ******************************************************************************/
  1050.  
  1051. void Destroy_Box(Object)
  1052. OBJECT *Object;
  1053. {
  1054.   Destroy_Transform(((BOX *)Object)->Trans);
  1055.  
  1056.   POV_FREE (Object);
  1057. }
  1058.  
  1059.  
  1060.  
  1061. /*****************************************************************************
  1062. *
  1063. * FUNCTION
  1064. *
  1065. *   Compute_Box_BBox
  1066. *
  1067. * INPUT
  1068. *
  1069. *   Box - Box
  1070. *
  1071. * OUTPUT
  1072. *
  1073. *   Box
  1074. *
  1075. * RETURNS
  1076. *
  1077. * AUTHOR
  1078. *
  1079. *   Dieter Bayer
  1080. *
  1081. * DESCRIPTION
  1082. *
  1083. *   Calculate the bounding box of a box.
  1084. *
  1085. * CHANGES
  1086. *
  1087. *   Aug 1994 : Creation.
  1088. *
  1089. ******************************************************************************/
  1090.  
  1091. void Compute_Box_BBox(Box)
  1092. BOX *Box;
  1093. {
  1094.   Assign_BBox_Vect(Box->BBox.Lower_Left, Box->bounds[0]);
  1095.  
  1096.   VSub(Box->BBox.Lengths, Box->bounds[1], Box->bounds[0]);
  1097.  
  1098.   if (Box->Trans != NULL)
  1099.   {
  1100.     Recompute_BBox(&Box->BBox, Box->Trans);
  1101.   }
  1102. }
  1103.  
  1104.